/*********************************************************************************
 * Copyright: Bernecker + Rainer
 * Author:    trostb
 * Created:   August 22, 2016/10:12 AM 
 *********************************************************************************/ 

#include <bur/plctypes.h>

#ifdef _DEFAULT_INCLUDES
	#include <AsDefault.h>
#endif
#include <string.h>






void _INIT ProgramInit(void)
{
	strcpy((void*)&TraceConvFileName, (void*)&"TraceData");
	CmdTraceConvStart = 0;

	strcpy((void*)&FileDevice, (void*)&"Trace");
	strcpy((void*)&FileType, (void*)&".csv");
	strcpy((void*)&FileASExtention, (void*)&"_AS");
	strcpy((void*)&ColumnSeparator, (void*)&";");

	strcpy((void*)&NetworkDevice, (void*)&"Network");
	strcpy((void*)&NetworkLinkPara, (void*)&"/SIP=10.40.1.1 /PROTOCOL=cifs /SHARE=Trace /USER=MyShareUser /PASSWORD=passwort");
//	strcpy((void*)&NetworkLinkPara, (void*)&"/SIP=10.40.1.1 /PROTOCOL=cifs /SHARE=Trace /USER=MyShareUser /PASSWORD=passwort");
//	strcpy((void*)&NetworkLinkPara, (void*)&"/SIP=10.40.1.1 /SNAME=ATEGGE3124 /PROTOCOL=cifs /SHARE=Trace /USER=MyShareUser /PASSWORD=passwort");
	
	
	// alloc buffer
	StatusBufferAlloc = ERR_OK;
	for(i=0;i<=MAX_TRACE_FILE;i++)
	{
		if(StatusBufferAlloc == ERR_OK)
			StatusBufferAlloc = TMP_alloc(MAX_TRACE_FILELEN, (void**)&AdrFileBuffer[i]);
	}
	if(StatusBufferAlloc == ERR_OK)
		StatusBufferAlloc = TMP_alloc(MAX_TRACE_FILELEN_SAVEHEADER, (void**)&AdrHeaderBuffer);
	if(StatusBufferAlloc == ERR_OK)
		StatusBufferAlloc = TMP_alloc(MAX_TRACE_FILELEN_SAVEDATA, (void**)&AdrSaveBuffer);
	
	
}






void _CYCLIC ProgramCyclic(void)
{

	switch(step)
	{
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// START CONVERT
		case 0:
			if(CmdTraceConvStart)
			{
				if(StatusBufferAlloc == ERR_OK)
				{
					memset((void*)&TraceConv, 0, sizeof(TraceConv));
	
					strcpy((void*)&TraceConv.Name, (void*)&TraceConvFileName);
					strcat((void*)&TraceConv.Name, (void*)&FileType);
					TraceConv.Adr = AdrFileBuffer[0];
					
					for(i=0;i<MAX_TRACE_FILE;i++)
					{
						TraceConv.File[i].Adr = AdrFileBuffer[i+1];
					}
					
					strcpy((void*)&TraceConv.Save.Name, (void*)&TraceConvFileName);
					strcat((void*)&TraceConv.Save.Name, (void*)&FileASExtention);
					strcat((void*)&TraceConv.Save.Name, (void*)&FileType);
					TraceConv.Save.Header.Adr = AdrHeaderBuffer;
					TraceConv.Save.Data.Adr = AdrSaveBuffer;
					
					step = 10;
				}
			}
		break;
		
		
		
		
		
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// READ FILES
		case 10:
			FileOpen_0.enable		= 1;
			FileOpen_0.pDevice		= (UDINT)&FileDevice;
			FileOpen_0.pFile		= (UDINT)&TraceConv.Name;
			FileOpen_0.mode			= fiREAD_ONLY;
			FileOpen(&FileOpen_0);
			if(FileOpen_0.status != ERR_FUB_BUSY)
			{
				if(FileOpen_0.status == ERR_OK)
				{
					TraceConv.Len = FileOpen_0.filelen;
					step = 11;
				}
				else
					step = 666;
			}
		break;

		case 11:
			FileRead_0.enable		= 1;
			FileRead_0.ident		= FileOpen_0.ident;
			FileRead_0.offset		= 0;
			FileRead_0.pDest		= (UDINT)TraceConv.Adr;
			FileRead_0.len			= TraceConv.Len;
			FileRead(&FileRead_0);
			if(FileRead_0.status != ERR_FUB_BUSY)
			{
				if(FileRead_0.status == ERR_OK)
					step = 12;
				else
					step = 666;
			}
		break;
		
		case 12:
			FileClose_0.enable		= 1;
			FileClose_0.ident		= FileOpen_0.ident;
			FileClose(&FileClose_0);
			if(FileClose_0.status != ERR_FUB_BUSY)
			{
				if(FileClose_0.status == ERR_OK)
				{
					step = 20;
				}
				else
					step = 666;
			}
		break;
		
		
		case 20:
			memset((void*)&CharRecordBuffer, 0, sizeof(CharRecordBuffer));
			CharRecordIx = 0;
			CntSeparatorThisLine = 0;
			
			for(k=0;k<TraceConv.Len;k++)
			{
				pChar = (USINT*) (TraceConv.Adr+k);
				if((*pChar == '\r') || (*pChar == '\n') || (*pChar == ColumnSeparator[0]))
				{
					if(CharRecordIx > 0)
					{
						switch(CntSeparatorThisLine)
						{
							case 0:
								strcpy((void*)&TraceConv.File[TraceConv.FileNum].Name, (void*)&CharRecordBuffer);
							break;
							case 1:
							case 2:
							case 3:
								// entries unused 
							break;
							default:
								TraceConv.File[TraceConv.FileNum].DataNum++;
								strcpy((void*)&TraceConv.Data[TraceConv.DataNum].Name, (void*)&CharRecordBuffer);
								TraceConv.Data[TraceConv.DataNum].FileIx = TraceConv.FileNum;
								TraceConv.Data[TraceConv.DataNum].DataIx = CntSeparatorThisLine-4;
								TraceConv.DataNum++;
							break;
						}
						if(*pChar == ColumnSeparator[0])
						{
							CntSeparatorThisLine++;
						}
						else
						{
							CntSeparatorThisLine = 0;
							TraceConv.FileNum++;
						}
					}
					memset((void*)&CharRecordBuffer, 0, sizeof(CharRecordBuffer));
					CharRecordIx = 0;
				}
				else
				{
					CharRecordBuffer[CharRecordIx] = *pChar;
					CharRecordIx++;
				}
				
			}
			CntFileNum = 0;
			step = 30;
		break;
		
		case 30:
			FileOpen_0.enable		= 1;
			FileOpen_0.pDevice		= (UDINT)&FileDevice;
			FileOpen_0.pFile		= (UDINT)&TraceConv.File[CntFileNum].Name;
			FileOpen_0.mode			= fiREAD_ONLY;
			FileOpen(&FileOpen_0);
			if(FileOpen_0.status != ERR_FUB_BUSY)
			{
				if(FileOpen_0.status == ERR_OK)
				{
					TraceConv.File[CntFileNum].Len = FileOpen_0.filelen;
					step = 31;
				}
				else
					step = 666;
			}
		break;

		case 31:
			FileRead_0.enable		= 1;
			FileRead_0.ident		= FileOpen_0.ident;
			FileRead_0.offset		= 0;
			FileRead_0.pDest		= (UDINT)TraceConv.File[CntFileNum].Adr;
			FileRead_0.len			= TraceConv.File[CntFileNum].Len;
			FileRead(&FileRead_0);
			if(FileRead_0.status != ERR_FUB_BUSY)
			{
				if(FileRead_0.status == ERR_OK)
					step = 32;
				else
					step = 666;
			}
		break;
		
		case 32:
			FileClose_0.enable		= 1;
			FileClose_0.ident		= FileOpen_0.ident;
			FileClose(&FileClose_0);
			if(FileClose_0.status != ERR_FUB_BUSY)
			{
				if(FileClose_0.status == ERR_OK)
				{
					step = 33;
				}
				else
					step = 666;
			}
		break;
		
		case 33:
			for(k=0;k<TraceConv.File[CntFileNum].Len;k++)
			{
				pChar = (USINT*) (TraceConv.File[CntFileNum].Adr+k);
				if(*pChar == '\n')
				{
					TraceConv.File[CntFileNum].CharRead = k+1;
					step = 34;
					break;
				}
			}
		break;
		
		case 34:
			CntFileNum++;
			if(CntFileNum >= TraceConv.FileNum)
				step = 100;
			else
				step = 30;
		break;
		
		
		
		
		
		
		
		
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// SORT DATA
		case 100:

			do
			{
				ValidDataFound = 0;
				for(i=0;i<TraceConv.FileNum;i++)
				{
					strcpy((void*)&TraceConv.File[i].DataTime, (void*)&"0");
					strcpy((void*)&TraceConv.File[i].Data[0], (void*)&"0");
					strcpy((void*)&TraceConv.File[i].Data[1], (void*)&"0");
					strcpy((void*)&TraceConv.File[i].Data[2], (void*)&"0");
					strcpy((void*)&TraceConv.File[i].Data[3], (void*)&"0");
					strcpy((void*)&TraceConv.File[i].Data[4], (void*)&"0");
					
				
					memset((void*)&CharRecordBuffer, 0, sizeof(CharRecordBuffer));
					CharRecordIx = 0;
					CntSeparatorThisLine = 0;

					for(k=TraceConv.File[i].CharRead ;k<TraceConv.File[i].Len;k++)
					{
						pChar = (USINT*) (TraceConv.File[i].Adr+k);
						if((*pChar == '\r') || (*pChar == '\n') || (*pChar == ColumnSeparator[0]))
						{
							if(CharRecordIx > 0)
							{
								switch(CntSeparatorThisLine)
								{
									case 0:
									case 1:
										// entries unused 
									break;
									case 2:
										strcpy((void*)&TraceConv.File[i].DataTime, (void*)&CharRecordBuffer);
									break;
									default:
										strcpy((void*)&TraceConv.File[i].Data[CntSeparatorThisLine-3], (void*)&CharRecordBuffer);
									break;
								}
								if(*pChar == ColumnSeparator[0])
								{
									CntSeparatorThisLine++;
								}
								else
								{
									CntSeparatorThisLine = 0;
								}
							}
							memset((void*)&CharRecordBuffer, 0, sizeof(CharRecordBuffer));
							CharRecordIx = 0;
						}
						else
						{
							CharRecordBuffer[CharRecordIx] = *pChar;
							CharRecordIx++;
						}
						if(*pChar == '\n')
						{
							ValidDataFound++;
							TraceConv.File[i].CharRead = k+1;
							break;
						}
					}
				}
	
				if(ValidDataFound)
				{
					strcpy((void*)&TempString, (void*)&"");
					for(i=0;i<TraceConv.DataNum;i++)
					{
						if(strcmp((void*)&TraceConv.File[TraceConv.Data[i].FileIx].DataTime, (void*)&"0") != 0)
						{
							TraceConv.Data[i].DataRows++;
						}
						strcat((void*)&TempString, (void*)&TraceConv.File[TraceConv.Data[i].FileIx].DataTime);
						strcat((void*)&TempString, (void*)&ColumnSeparator);
						strcat((void*)&TempString, (void*)&TraceConv.File[TraceConv.Data[i].FileIx].Data[TraceConv.Data[i].DataIx]);
						strcat((void*)&TempString, (void*)&ColumnSeparator);
					}
					strcat((void*)&TempString, (void*)&"\r\n");
					TempStringLen = strlen((void*)&TempString);
					memcpy((void*)(TraceConv.Save.Data.Adr+TraceConv.Save.Data.Len), (void*)&TempString, TempStringLen);
					TraceConv.Save.Data.Len += TempStringLen;
				}
			}
			while(ValidDataFound);

			step = 190;
		break;
	
		
		case 190:
			strcpy((void*)TraceConv.Save.Header.Adr, (void*)&"");
			for(i=0;i<TraceConv.DataNum;i++)
			{
				strcat((void*)TraceConv.Save.Header.Adr, (void*)&"% TYPE=CHART-DATA-ASCII V=2,0 TITLE=\"");
				strcat((void*)TraceConv.Save.Header.Adr, (void*)&TraceConv.Data[i].Name);
				strcat((void*)TraceConv.Save.Header.Adr, (void*)&"\" XUNIT=\"UnitX\" YUNIT=\"UnitY\" FORMULA=\"DO_NOT_CHANGE_ORIGINAL_DATA\" ROWS=");
				brsitoa(TraceConv.Data[i].DataRows, (UDINT)&TempString);
				strcat((void*)TraceConv.Save.Header.Adr, (void*)&TempString);
				strcat((void*)TraceConv.Save.Header.Adr, (void*)&" COLS=2 COLSEP=\"SEMICOLON\" ;\r\n");
			}
			TraceConv.Save.Header.Len = strlen((void*)TraceConv.Save.Header.Adr);
			step = 200;
		break;
	
		
		
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// SAVE CONVERTED FILE
		case 200:
			FileDelete_0.enable		= 1;
			FileDelete_0.pDevice	= (UDINT)&FileDevice;
			FileDelete_0.pName		= (UDINT)&TraceConv.Save.Name;
			FileDelete(&FileDelete_0);
			if(FileDelete_0.status != ERR_FUB_BUSY)
			{
				if((FileDelete_0.status == ERR_OK) || (FileDelete_0.status == fiERR_FILE_NOT_FOUND))
					step = 201;
				else
					step = 666;
			}
		break;
		
		case 201:
			FileCreate_0.enable		= 1;
			FileCreate_0.pDevice	= (UDINT)&FileDevice;
			FileCreate_0.pFile		= (UDINT)&TraceConv.Save.Name;
			FileCreate(&FileCreate_0);
			if(FileCreate_0.status != ERR_FUB_BUSY)
			{
				if(FileCreate_0.status == ERR_OK)
					step = 210;
				else
					step = 666;
			}
		break;
		
		case 210:
			FileWrite_0.enable		= 1;
			FileWrite_0.ident		= FileCreate_0.ident;
			FileWrite_0.offset		= 0;
			FileWrite_0.pSrc		= TraceConv.Save.Header.Adr;
			FileWrite_0.len			= TraceConv.Save.Header.Len;
			FileWrite(&FileWrite_0);
			if(FileWrite_0.status != ERR_FUB_BUSY)
			{
				if(FileWrite_0.status == ERR_OK)
					step = 211;
				else
					step = 666;
			}
		break;
		
		case 211:
			FileWrite_0.enable		= 1;
			FileWrite_0.ident		= FileCreate_0.ident;
			FileWrite_0.offset		= TraceConv.Save.Header.Len;
			FileWrite_0.pSrc		= TraceConv.Save.Data.Adr;
			FileWrite_0.len			= TraceConv.Save.Data.Len;
			FileWrite(&FileWrite_0);
			if(FileWrite_0.status != ERR_FUB_BUSY)
			{
				if(FileWrite_0.status == ERR_OK)
					step = 220;
				else
					step = 666;
			}
		break;
		
		case 220:
			FileClose_0.enable		= 1;
			FileClose_0.ident		= FileCreate_0.ident;
			FileClose(&FileClose_0);
			if(FileClose_0.status != ERR_FUB_BUSY)
			{
				if(FileClose_0.status == ERR_OK)
				{
					CmdTraceConvStart = 0;
					step = 0;
				}
				else
					step = 666;
			}
		break;
		
		
		
		case 300:
			DevLink_0.enable		= 1;
			DevLink_0.pDevice		= (UDINT)&NetworkDevice;
			DevLink_0.pParam		= (UDINT)&NetworkLinkPara;
			DevLink(&DevLink_0);
			if(DevLink_0.status != ERR_FUB_BUSY)
			{
				step = 0;
				if(DevLink_0.status == fiERR_SYSTEM)
					FileIoSysError = FileIoGetSysError();
			}
		break;
		
		case 301:
			FileCopy_0.enable		= 1;
			FileCopy_0.pSrcDev		= (UDINT)&FileDevice;
			FileCopy_0.pSrc			= (UDINT)&TraceConv.Save.Name;
			FileCopy_0.pSrcDev		= (UDINT)&NetworkDevice;
			FileCopy_0.pDest		= (UDINT)&TraceConv.Save.Name;
			FileCopy_0.option		= fiOVERWRITE;
			FileCopy(&FileCopy_0);
			if(FileCopy_0.status != ERR_FUB_BUSY)
			{
				if(FileCopy_0.status == ERR_OK)
				{
					step = 0;
				}
				else
					step = 666;
			}
		
		
		
		break;
		
		
		
		
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// ERROR
		case 666:
			if(CmdTraceConvStart == 0)
			{
				step = 0;
			}
		break;
	}

}












void _EXIT ProgramExit(void)
{
	for(i=0;i<=MAX_TRACE_FILE;i++)
	{
		if(AdrFileBuffer[i] != 0)
			TMP_free(MAX_TRACE_FILELEN, (void**)AdrFileBuffer[i]);
	}
	if(AdrSaveBuffer != 0)
		TMP_alloc(MAX_TRACE_FILELEN_SAVEDATA, (void**)&AdrSaveBuffer);
	if(AdrHeaderBuffer != 0)
		TMP_alloc(MAX_TRACE_FILELEN_SAVEDATA, (void**)&AdrHeaderBuffer);
}

